using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace CursorFollower
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 origin;
        Vector2 mousePos;
        float angle;
        float distance;
        float opp;
        float adj;
        Texture2D tex;
        Texture2D bleh;
        SpriteFont myFont;
        string quadrant;

        #region shit
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            origin = new Vector2((float)this.Window.ClientBounds.Width / 2, (float)this.Window.ClientBounds.Height / 2);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            this.tex = Content.Load<Texture2D>("whitepx");
            this.bleh = Content.Load<Texture2D>("bleh");
            this.myFont = Content.Load<SpriteFont>("MyFont");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }
        #endregion

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            MouseState mouseState = Mouse.GetState();
            this.mousePos.X = mouseState.X;
            this.mousePos.Y = mouseState.Y;

            UpdateAngleAndDistance_NewStyle();
            //UpdateAngleAndDistance_OldStyle();

            base.Update(gameTime);
        }

        public void UpdateAngleAndDistance_NewStyle()
        {            
            Vector2 direction = this.mousePos - this.origin;
            this.angle = (float)Math.Atan2((double)direction.Y, (double)direction.X);
            this.distance = direction.Length();            
        }

        public void UpdateAngleAndDistance_OldStyle()
        {
            this.opp = Math.Abs(origin.Y - mousePos.Y);
            this.adj = Math.Abs(origin.X - mousePos.X );
            this.distance = (float)Math.Sqrt((double)((opp*opp) + (adj*adj)));

            this.angle = (float)Math.Atan(opp / adj);
            
            
            // quadrant top-right
            if (mousePos.X > origin.X && mousePos.Y < origin.Y) 
            {
               // take angle as is    
                this.quadrant = "Top-right";
            } 
            // quadrant top-left
            else if(mousePos.X < origin.X && mousePos.Y < origin.Y) 
            {
                angle = MathHelper.Pi - angle;
                this.quadrant = "Top-left";
            }
            // quadrant bottom-left
            else if(mousePos.X < origin.X && mousePos.Y > origin.Y)
            {
                angle = MathHelper.Pi + angle;
                this.quadrant = "Bottom-left";
            }
            // bottom-right
            else if(mousePos.X > origin.X && mousePos.Y > origin.Y)
            {
                angle = 2 * MathHelper.Pi - angle;
                this.quadrant = "Bottom-right";
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            this.spriteBatch.Begin();           
            
            // draw the origin and cursor positions
            this.spriteBatch.Draw(tex, new Rectangle((int)this.origin.X, (int)this.origin.Y, 10, 10), Color.Wheat);
            this.spriteBatch.Draw(bleh, new Rectangle((int)this.mousePos.X, (int)this.mousePos.Y, 16, 16), Color.White);
            
            // here's the magick!
            DrawLine_NewStyle();
            //DrawLine_OldStyle();

            this.spriteBatch.End();
            base.Draw(gameTime);
        }

        public void DrawLine_NewStyle()
        {
            this.spriteBatch.DrawString(this.myFont, "Angle: " + angle.ToString(), new Vector2(100, 100), Color.Green);
            this.spriteBatch.Draw(
                this.tex, // texture
                this.origin, // position
                null, // source rectangle
                Color.Red,
                angle,
                new Vector2(0), // rotation origin
                new Vector2(2, distance), // scaling
                SpriteEffects.None,
                0);
        }

        public void DrawLine_OldStyle()
        {            
            this.spriteBatch.Draw(tex, origin, null, Color.Green, /*-(*/angle/* + MathHelper.PiOver2)*/, new Vector2(0), new Vector2(1, distance), SpriteEffects.None, 0);

            this.spriteBatch.DrawString(this.myFont, "Angle: " + angle.ToString(), new Vector2(100, 100), Color.Green);
            this.spriteBatch.DrawString(this.myFont, "Degrees: " + MathHelper.ToDegrees(angle).ToString(), new Vector2(100, 125), Color.Green);
            this.spriteBatch.DrawString(this.myFont, "Mouse.X: " + mousePos.X, new Vector2(100, 150), Color.Green);
            this.spriteBatch.DrawString(this.myFont, "Mouse.Y: " + mousePos.Y, new Vector2(100, 175), Color.Green);
            this.spriteBatch.DrawString(this.myFont, "Origin.X: " + origin.X, new Vector2(100, 200), Color.Green);
            this.spriteBatch.DrawString(this.myFont, "Origin.Y: " + origin.Y, new Vector2(100, 225), Color.Green);
            this.spriteBatch.DrawString(this.myFont, "Quadrant: " + this.quadrant, new Vector2(100, 250), Color.Green);
        }
    }
}
